001 /* 002 * Copyright 2005 Stephen J. McConnell. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.transit.local; 020 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.FileInputStream; 024 import java.io.OutputStream; 025 import java.io.FileOutputStream; 026 import java.io.File; 027 import java.net.URL; 028 import java.net.URLConnection; 029 import java.security.AccessController; 030 import java.security.PrivilegedExceptionAction; 031 import java.security.PrivilegedActionException; 032 import java.security.PrivilegedAction; 033 034 import net.dpml.transit.Transit; 035 import net.dpml.transit.Artifact; 036 037 /** 038 * The local URL protocol connection implementation. 039 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 040 * @version 1.0.1 041 */ 042 public class LocalURLConnection extends URLConnection 043 { 044 private boolean m_connected; 045 046 private File m_target; 047 048 /** 049 * Creation of a new local handler. 050 * @param url the url to establish a connection with 051 * @exception NullPointerException if the url argument is null 052 */ 053 LocalURLConnection( URL url ) 054 throws NullPointerException 055 { 056 super( url ); 057 058 m_connected = false; 059 } 060 061 /** 062 * Establish a connection. 063 * 064 * @exception IOException is an error occurs while attempting to establish 065 * the connection. 066 */ 067 public void connect() 068 throws IOException 069 { 070 if( m_connected ) 071 { 072 return; 073 } 074 075 m_connected = true; 076 077 try 078 { 079 AccessController.doPrivileged( 080 new PrivilegedExceptionAction() 081 { 082 public Object run() 083 throws IOException 084 { 085 String spec = url.toExternalForm(); 086 try 087 { 088 Artifact artifact = Artifact.createArtifact( spec ); 089 String groupSpec = artifact.getGroup(); 090 String artifactName = artifact.getName(); 091 String typeSpec = artifact.getType(); 092 String versionSpec = artifact.getVersion(); 093 File prefs = Transit.DPML_PREFS; 094 File group = new File( prefs, groupSpec ); 095 File type = new File( group, typeSpec + "s" ); 096 if( null == versionSpec ) 097 { 098 final String filename = artifactName + "." + typeSpec; 099 m_target = new File( type, filename ); 100 } 101 else 102 { 103 final String filename = artifactName + "-" + versionSpec + "." + typeSpec; 104 m_target = new File( type, filename ); 105 } 106 } 107 catch( Throwable e ) 108 { 109 String message = e.getMessage(); 110 IOException exception = new IOException( message ); 111 exception.initCause( e.getCause() ); 112 throw exception; 113 } 114 return null; // nothing to return 115 } 116 } 117 ); 118 } 119 catch( PrivilegedActionException e ) 120 { 121 throw (IOException) e.getException(); 122 } 123 } 124 125 /** 126 * Return an input stream to the resource. 127 * @return the input stream 128 * @exception IOException is an error occurs 129 */ 130 public InputStream getInputStream() 131 throws IOException 132 { 133 connect(); 134 if( m_target == null ) 135 { 136 return null; 137 } 138 else 139 { 140 return new FileInputStream( m_target ); 141 } 142 } 143 144 /** 145 * Return an output stream to the resource. 146 * @return the output stream 147 * @exception IOException if any I/O problems occur. 148 */ 149 public OutputStream getOutputStream() 150 throws IOException 151 { 152 connect(); 153 if( m_target == null ) 154 { 155 return null; 156 } 157 else 158 { 159 if( !m_target.exists() ) 160 { 161 File parent = m_target.getParentFile(); 162 if( null != parent ) 163 { 164 parent.mkdirs(); 165 } 166 m_target.createNewFile(); 167 } 168 return new FileOutputStream( m_target ); 169 } 170 } 171 172 /** 173 * Return the content for this local resource. 174 * @param classes a sequence of classes against which the 175 * implementation will attempt to establish a known match 176 * @return the content object (possibly null) 177 * @exception IOException is an error occurs 178 */ 179 public Object getContent( final Class[] classes ) 180 throws IOException 181 { 182 connect(); 183 Object result = AccessController.doPrivileged( 184 new PrivilegedAction() 185 { 186 public Object run() 187 { 188 for( int i=0; i < classes.length; i++ ) 189 { 190 Class c = classes[i]; 191 if( c.equals( File.class ) ) 192 { 193 return m_target; 194 } 195 } 196 return null; 197 } 198 } 199 ); 200 201 if( null != result ) 202 { 203 return result; 204 } 205 else 206 { 207 if( null != m_target ) 208 { 209 return m_target.toURL().getContent( classes ); 210 } 211 else 212 { 213 return super.getContent( classes ); 214 } 215 } 216 } 217 }